# encoding: utf-8  
'''
Created on 2018年8月14日
description:Windows系统信息收集
@author: zhujianhua
'''
import sys
import wmi
import time
import requests
import json
import win32com.client as client
sys.path.append('./../helper')
import InfoMonConstants
from LoggerHelper import LoggerHelper
  
class WinSystemInfo(object):
    def __init__(self, host='127.0.0.1', user='', passwd=''):
        self.host = host
        self.user = user
        self.password = passwd 
        self.uploadData = [] #收集数据列表
        self.ts = int(time.time()) #时间戳
        self.logger = LoggerHelper("WinSystemInfo")
        self.logger.info('collecting infomation from ' + self.host)
          
    def run(self):
        if self.host != '127.0.0.1':
            try:
                self.wmi = wmi.WMI(computer=self.host, user=self.user, password=self.password)
            except Exception as e:
                self.logger.error('failed to connect to ' + self.host)
                self.logger.error(str(e))
                return
        else:
            self.wmi = wmi.WMI()
        self.collect()
        # print(self.uploadData)
        self.send()
          
        #数据收集
    def collect(self):
        try:
            self.getCpuUsage()
            self.getMemoryInfo()
            self.getDiskInfo()
            self.getNetworkInfo()
   
        except Exception as e:
            self.logger.error(str(e))
        finally:
            pass
          
              
        #发送数据到transfer
    def send(self):
        if 0 != len(self.uploadData):
            self.logger.info("sending data to " +InfoMonConstants.FALCON_CLINENT)
            try:
                r = requests.post(InfoMonConstants.FALCON_CLINENT, data=json.dumps(self.uploadData))
                self.logger.info(r.text)
            except requests.exceptions.ConnectionError:
                self.logger.error('failed to connect to ' + InfoMonConstants.FALCON_CLINENT)
                self.logger.error('transfer data failed')
              
      
    def getCpuUsage(self):
        for cpu in self.wmi.Win32_Processor():
            device = cpu.DeviceID.lower()
            # Get cpu_usage
            self.uploadData.append({
            "endpoint": InfoMonConstants.ENDPOINT,
            "metric": "system_cpu_usage",
            "timestamp": self.ts,
            "step": 60,
            "value": float(cpu.LoadPercentage),
            "counterType": "GAUGE",
            "tags": "device=" + device,
            })
      
    def getMemoryInfo(self):
        cs = self.wmi.Win32_ComputerSystem() 
        self.uploadData.append({
            "endpoint": InfoMonConstants.ENDPOINT,
            "metric": "system_memory_total",
            "timestamp": self.ts,
            "step": 60,
            "value": float(cs[0].TotalPhysicalMemory) / (1024*1024),
            "counterType": "GAUGE",
            "tags": "unit=MB",
            })
        os = self.wmi.Win32_OperatingSystem() 
        self.uploadData.append({
            "endpoint": InfoMonConstants.ENDPOINT,
            "metric": "system_memory_free",
            "timestamp": self.ts,
            "step": 60,
            "value": float(os[0].FreePhysicalMemory)/1024,
            "counterType": "GAUGE",
            "tags": "unit=MB",
            })
        pfu = self.wmi.Win32_PageFileUsage()
        self.uploadData.append({
            "endpoint": InfoMonConstants.ENDPOINT,
            "metric": "system_swap_total",
            "timestamp": self.ts,
            "step": 60,
            "value": float(pfu[0].AllocatedBaseSize),
            "counterType": "GAUGE",
            "tags": "unit=MB",
            })
        self.uploadData.append({
            "endpoint": InfoMonConstants.ENDPOINT,
            "metric": "system_swap_free",
            "timestamp": self.ts,
            "step": 60,
            "value": float(pfu[0].AllocatedBaseSize - pfu[0].CurrentUsage),
            "counterType": "GAUGE",
            "tags": "unit=MB",
            })       
          
    def getDiskInfo(self):
        diskDict = {}
        for disk in self.wmi.Win32_LogicalDisk (DriveType=3):
            self.uploadData.append({
                "endpoint": InfoMonConstants.ENDPOINT,
                "metric": "diskspace_free",
                "timestamp": self.ts,
                "step": 60,
                "value": round(float(disk.FreeSpace) / (1024*1024*1024), 2),
                "counterType": "GAUGE",
                "tags": "deviceid=" + disk.DeviceID,
                })       
            self.uploadData.append({
                "endpoint": InfoMonConstants.ENDPOINT,
                "metric": "diskspace_total",
                "timestamp": self.ts,
                "step": 60,
                "value": round(float(disk.Size) / (1024*1024*1024), 2),
                "counterType": "GAUGE",
                "tags": "deviceid=" + disk.DeviceID,
                })
            diskDict[disk.DeviceID] = disk.DeviceID
                    
 
        com = client.Dispatch("WbemScripting.SWbemRefresher")
        obj = client.GetObject("winmgmts:\\root\cimv2")
        diskitems = com.AddEnum(obj, "Win32_PerfFormattedData_PerfDisk_LogicalDisk").objectSet
          
        com.Refresh()
        for item in diskitems:
            if item.Name in diskDict:
                self.uploadData.append({
                    "endpoint": InfoMonConstants.ENDPOINT,
                    "metric": "diskspace_write_bytes_per_sec",
                    "timestamp": self.ts,
                    "step": 60,
                    "value": float(item.DiskWritesPerSec),
                    "counterType": "GAUGE",
                    "tags": "deviceid=" + disk.DeviceID,
                    })   
                self.uploadData.append({
                    "endpoint": InfoMonConstants.ENDPOINT,
                    "metric": "diskspace_read_bytes_per_sec",
                    "timestamp": self.ts,
                    "step": 60,
                    "value": float(item.DiskReadsPerSec),
                    "counterType": "GAUGE",
                    "tags": "deviceid=" + disk.DeviceID,
                    })  
  
    def getNetworkInfo(self):
        com = client.Dispatch("WbemScripting.SWbemRefresher")
        obj = client.GetObject("winmgmts:\\root\cimv2")
        items = com.AddEnum(obj, "Win32_PerfRawData_Tcpip_NetworkInterface").objectSet
   
        interfaces = []
        for interface in self.wmi.Win32_NetworkAdapterConfiguration (IPEnabled=1):
            interfaces.append(interface.Description)
   
        net_bytes_in = 0
        net_bytes_out = 0
        net_pkts_in = 0
        net_pkts_out = 0
          
        com.Refresh()
        for item in items:
            if item.Name in interfaces:
                net_bytes_in += int(item.BytesReceivedPerSec)
                net_bytes_out += int(item.BytesSentPerSec)
                net_pkts_in += int(item.PacketsReceivedPerSec)
                net_pkts_out += int(item.PacketsSentPerSec)
   
        time.sleep(1)
        com.Refresh()
        for item in items:
            if item.Name in interfaces:
                net_bytes_in = int(item.BytesReceivedPerSec) - net_bytes_in
                net_bytes_out = int(item.BytesSentPerSec) - net_bytes_out
                net_pkts_in = int(item.PacketsReceivedPerSec) - net_pkts_in
                net_pkts_out = int(item.PacketsSentPerSec) - net_pkts_out
   
        self.uploadData.append({
            "endpoint": InfoMonConstants.ENDPOINT,
            "metric": "system_network_bytes_received_per_sec",
            "timestamp": self.ts,
            "step": 60,
            "value": net_bytes_in,
            "counterType": "GAUGE",
            "tags": "",
            }) 
        self.uploadData.append({
            "endpoint": InfoMonConstants.ENDPOINT,
            "metric": "system_network_bytes_send_per_sec",
            "timestamp": self.ts,
            "step": 60,
            "value": net_bytes_out,
            "counterType": "GAUGE",
            "tags": "",
            })
        self.uploadData.append({
            "endpoint": InfoMonConstants.ENDPOINT,
            "metric": "system_network_packets_received_per_sec",
            "timestamp": self.ts,
            "step": 60,
            "value": net_pkts_in,
            "counterType": "GAUGE",
            "tags": "",
            })
        self.uploadData.append({
            "endpoint": InfoMonConstants.ENDPOINT,
            "metric": "system_network_packets_send_per_sec",
            "timestamp": self.ts,
            "step": 60,
            "value": net_pkts_out,
            "counterType": "GAUGE",
            "tags": "",
            })     

